<?php

namespace App\Service\Workflow;

use App\Enums\Workflow\WorkflowEnum;
use App\Library\FeiShu\SendFs;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\Cruise\CruiseTemplatePositionProjectMappingModel;
use App\Models\Workflow\WorkflowTemplateModel;
use App\Models\Workflow\WorkflowTemplateNodeModel;
use App\Service\BaseService;
use App\Service\Cruise\CruiseTemplate\CruiseTemplateService;
use Illuminate\Support\Facades\DB;
use Kuafu\GeneralFs\BuildFs;

class WorkflowTemplateService extends BaseService
{
    private int $currentUserId;
    private string $currentUserName;

    public function __construct(int $uid, string $username)
    {
        $this->currentUserId   = $uid;
        $this->currentUserName = $username;
    }

    public function addOrEdit(int $templateId, string $name, int $workflowType, array $nodes): int
    {
        // 记录nodeKey => nodeId
        $nodeKeyToNodeId = [];

        DB::beginTransaction();

        // workflow_template 模板
        $workflowTemplateModel               = WorkflowTemplateModel::query()->firstOrNew(['id' => $templateId]);
        $oldWorkflowTemplateModel            = clone $workflowTemplateModel;
        $oldWorkflowTemplateNodes            = $oldWorkflowTemplateModel->nodes;

        $workflowTemplateModel->name         = $name;
        $workflowTemplateModel->workflowType = $workflowType;
        if ($templateId == 0) {
            $workflowTemplateModel->status = WorkflowTemplateModel::STATUS_OFF;
        }
        $workflowTemplateModel->save();

        // 删除原有数据 - 硬删
        if ($templateId != 0) {
            $this->delete($templateId, false, false);
        }

        foreach ($nodes as $k => $node) {

            if ($k == 0) {
                $prevId = 0;
            } else {
                $prevId = $nodeModel->id;
            }

            // 表单校验
            if (isset($node['cruiseTemplateId']) && $node['cruiseTemplateId']) {
                $cruiseTemplate = CruiseTemplateModel::query()->find((int)$node['cruiseTemplateId']);
                if (!$cruiseTemplate) {
                    BaseService::throwErr("表单配置不存在:{$node["cruiseTemplateId"]}");
                }

                if ($cruiseTemplate->status != CruiseTemplateModel::STATUS_ON) {
                    BaseService::throwErr("表单配置已停用:{$node["cruiseTemplateId"]}");
                }
            }

            // workflow_template_node - 主节点、父节点
            $nodeModel = WorkflowTemplateNodeModel::query()->create([
                'workflowTemplateId' => $workflowTemplateModel->id,
                'pId'                => 0,
                'nextId'             => 0,
                'prevId'             => $prevId,
                'businessType'       => $node['businessType'],
                'name'               => $node['name'],
                'nodeType'           => $node['nodeType'],
                'handlerType'        => $node['handlerType'],
                'handlerUid'         => $node['handlerUid'] ?? 0,
                'status'             => WorkflowTemplateModel::STATUS_ON,
                'cruiseTemplateId'   => $node['cruiseTemplateId'] ?? 0,
            ]);

            $nodeKeyToNodeId[$node['nodeKey']] = $nodeModel->id;

            // 除了最后一个节点，更新上个节点的nextId
            WorkflowTemplateNodeModel::query()->where('id', $prevId)->update(['nextId' => $nodeModel->id]);

            // 子节点
            if (isset($node['children'])) {
                foreach ($node['children'] as $childrenNode) {

                    // 校验nodeKey
                    $nodeKey = $childrenNode['condition']['nodeKey'];
                    if (!isset($nodeKeyToNodeId[$nodeKey])) {
                        BaseService::throwErr("之前的流程不存在的nodeKey:{$nodeKey}");
                    }

                    $cruiseNode = collect($nodes)->where('nodeKey', $nodeKey)->first();
                    if (!$cruiseNode) {
                        BaseService::throwErr("nodeKey:{$nodeKey}不存在");
                    }

                    // 校验该node的cruise_template
                    if (!isset($cruiseNode['cruiseTemplateId']) || !$cruiseNode['cruiseTemplateId']) {
                        BaseService::throwErr("nodeKey:{$nodeKey} 不存在cruiseTemplateId");
                    }

                    $cruiseTemplateId = $cruiseNode['cruiseTemplateId'];
                    $cruiseProjectId  = $childrenNode['condition']['projectId'];
                    $checkProjectId   = CruiseTemplatePositionProjectMappingModel
                        ::query()
                        ->where('templateId', $cruiseTemplateId)
                        ->where('projectId', $cruiseProjectId)
                        ->first();
                    if (!$checkProjectId) {
                        BaseService::throwErr("cruiseTemplateId:{$cruiseTemplateId}中不包含projectId:{$cruiseProjectId}");
                    }

                    $childrenNode['condition']['nodeId'] = $nodeKeyToNodeId[$nodeKey];
                    unset($childrenNode['condition']['nodeKey']);

                    WorkflowTemplateNodeModel::query()->create([
                        'workflowTemplateId' => $workflowTemplateModel->id,
                        'pId'                => $nodeModel->id,
                        'businessType'       => $childrenNode['businessType'],
                        'name'               => WorkflowEnum::BUSINESS_TYPE_TEXT[$childrenNode['businessType']],
                        'nodeType'           => 0,
                        'condition'          => json_encode($childrenNode['condition'] ?? [], JSON_UNESCAPED_UNICODE),
                    ]);
                }
            }
        }

        DB::commit();

        if ($templateId) {
            $title = "编辑";
        } else {
            $title = "新增";
        }

        $oldNodesJson = json_encode($oldWorkflowTemplateNodes, JSON_UNESCAPED_UNICODE);
        $newNodesJson = json_encode($nodes, JSON_UNESCAPED_UNICODE);

        // 审计日志
        $content = vsprintf("工作审批流模板【{$title}】 \n\n  id:%s \n\n name:%s => %s \n\n workflowType:%s => %s \n\n oldNodes:%s \n\n newNodes:%s \n\n 操作人:%s-%s", [
            $templateId,
            $oldWorkflowTemplateModel->name ?? '',
            $name,
            $oldWorkflowTemplateModel->workflowType ?? '',
            $workflowType,
            $oldNodesJson,
            $newNodesJson,
            $this->currentUserName,
            $this->currentUserId
        ]);
        $this->auditFs($content);

        return $workflowTemplateModel->id;
    }

    /**
     * 列表
     * @param int $pageNum
     * @param int $pageSize
     * @param int $status
     * @param int $workflowType
     * @return array
     */
    public function index(int $pageNum, int $pageSize, int $status, int $workflowType): array
    {
        $paginator = WorkflowTemplateModel::query()
                                          ->when($status != -1, function ($query) use ($status) {
                                              $query->where('status', $status);
                                          })
                                          ->when($workflowType, function ($query) use ($workflowType) {
                                              $query->where('workflowType', $workflowType);
                                          })
                                          ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        return BaseService::pageLists($paginator, function ($item) {
            return [
                'id'           => $item->id,
                'name'         => $item->name,
                'workflowType' => $item->workflowType,
                'status'       => $item->status,
                'statusText'   => WorkflowTemplateModel::STATUS_TEXT[$item->status] ?? '-',
                'createdAt'    => $item->createdAt->toDateTimeString(),
            ];
        });
    }

    /**
     * 详情
     * @param int $id
     * @return array
     */
    public function detail(int $id): array
    {
        $template = WorkflowTemplateModel::query()->find($id);
        if (!$template) {
            BaseService::throwErr('不存在的模板id');
        }

        $nodes = WorkflowTemplateNodeModel
            ::query()
            ->where('workflowTemplateId', $id)
            ->where('pId', 0)
            ->get()
            ->map(function (WorkflowTemplateNodeModel $nodeModel) {

                $data = [
                    'id'               => $nodeModel->id,
                    'name'             => $nodeModel->name,
                    'nodeType'         => $nodeModel->nodeType,
                    'businessType'     => $nodeModel->businessType,
                    'handlerType'      => $nodeModel->handlerType,
                    'handlerUid'       => $nodeModel->handlerUid,
                    'cruiseTemplateId' => $nodeModel->cruiseTemplateId,
                    'children'         => $nodeModel->childrenRel
                        ->map(function (WorkflowTemplateNodeModel $childNodeModel) {
                            $condition = json_decode($childNodeModel->condition, true);
                            return [
                                'name'      => $childNodeModel->name,
                                'condition' => $condition,
                            ];
                        }),
                ];

                if (!$data['children']->count()) {
                    unset($data['children']);
                }

                return $data;
            });

        return [
            'name'         => $template->name,
            'workflowType' => $template->workflowType,
            'nodes'        => $nodes,
        ];
    }

    /**
     * 删除
     * @param int $id
     * @return void
     */
    public function delete(int $id, bool $softDeleted = true, bool $deleteWorkflowTemplate = true): void
    {
        $template = WorkflowTemplateModel::query()->find($id);
        if (!$template) {
            BaseService::throwErr('不存在的模板id，或已删除');
        }

        DB::beginTransaction();

        if ($softDeleted) {

            // 节点相关
            WorkflowTemplateNodeModel::query()->where('workflowTemplateId', $id)->update(['isDeleted' => 1]);
            if ($deleteWorkflowTemplate) {
                WorkflowTemplateModel::query()->where('id', $id)->update(['isDeleted' => 1]);
            }

        } else {

            // 节点相关
            WorkflowTemplateNodeModel::query()->where('workflowTemplateId', $id)->delete();
            if ($deleteWorkflowTemplate) {
                WorkflowTemplateModel::query()->where('id', $id)->delete();
            }
        }

        DB::commit();

        // 审计日志
        $content = vsprintf("工作审批流模板【删除】\n\n id:%s name:%s \n\n 操作人:%s-%s", [
            $template->id,
            $template->name,
            $this->currentUserName,
            $this->currentUserId
        ]);
        $this->auditFs($content);
    }

    // 上下架
    public function onOff(int $id, int $status)
    {
        $template = WorkflowTemplateModel::query()->find($id);
        if (!$template) {
            BaseService::throwErr('不存在的模板id，或已删除');
        }

        $template->status = $status;
        $template->save();

        $statusText = WorkflowTemplateModel::STATUS_TEXT[$status] ?? '-';

        // 审计日志
        $content = vsprintf("工作审批流模板【{$statusText}】\n\n id:%s name:%s \n\n操作人:%s-%s", [
            $template->id,
            $template->name,
            $this->currentUserName,
            $this->currentUserId
        ]);
        $this->auditFs($content);
    }

    /**
     * 飞书审计消息
     * @return void
     */
    private function auditFs(string $content)
    {
        BuildFs::newRobot(SendFs::ROBOT_AUDIT_LOG)->setTitleContent("工作审批流 - 审计消息", $content)->send();
    }
}
